package chzhenjia.learn.androidcode.four;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;

/**
 * 作者:陈圳佳
 * 日期:2015/8/5
 */
public class MultiDownload {

    /**
     * 线程的数量
     */
    public static final int THREAD_COUNT = 3;
    private final String url;
    private int successThread;

    public MultiDownload(String url) {
        this.url = url;
    }

    public static void connectionFromUrl(final String url, final HttpOk httpOk) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    HttpURLConnection conn = getConnection(url);
                    conn.connect();
                    if (conn.getResponseCode() == 200)
                        httpOk.callback(conn);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private static HttpURLConnection getConnection(String url) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setConnectTimeout(4000);
        conn.setRequestMethod("GET");
//        conn.setReadTimeout(4000);
        return conn;
    }

    public void start(final File dir) {
        connectionFromUrl(url, new HttpOk() {
            @Override
            public void callback(HttpURLConnection conn) throws Exception {
                int length = conn.getContentLength();
                String fileName = url.substring(url.lastIndexOf("/") + 1);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dir, fileName);
                RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
                accessFile.setLength(length);
                accessFile.close();
                int size = length / THREAD_COUNT;
                for (int i = 0; i < THREAD_COUNT; i++) {
                    int start = i * size;
                    int end = i == THREAD_COUNT - 1 ? length : (i + 1) * size;
                    end -= 1;
                    new Thread(new DownloadThread(start, end, i, file)).start();
                }
            }
        });
    }

    public void start(String path) {
        start(new File(path));
    }

    interface HttpOk {
        void callback(HttpURLConnection conn) throws Exception;
    }

    class DownloadThread implements Runnable {
        private final File file;
        private final int threadId;
        private final File prog;
        private int startIndex;
        private int endIndex;
        private int[] seeks = new int[]{
                32, 45, 58
        };
//        private int seek;

        public DownloadThread(int startIndex, int endIndex, int threadId, File file) {
            this.startIndex = startIndex;
            this.endIndex = endIndex;
            this.file = file;
            this.threadId = threadId;
            prog = new File(file.getParent(), file.getName() + ".temp");
            try {
                if (!prog.exists()) {
                    boolean newFile = prog.createNewFile();
                    if (newFile) {
                        FileWriter writer = new FileWriter(prog);
                        Properties properties = new Properties();
                        for (int i = 0; i < THREAD_COUNT; i++) {
                            properties.setProperty(i + "", "0         ");
                        }
                        properties.store(writer, null);
                        writer.close();
                    }
                }
                Properties properties = new Properties();
                properties.load(new FileReader(prog));
                this.startIndex = Integer.parseInt(properties.getProperty(threadId + "").trim());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
//            int seek = 0;
            try {
                HttpURLConnection conn = getConnection(url);
                conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
                conn.connect();
                //注意：请求部分数据是206
                if (conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {
                    RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
                    InputStream is = conn.getInputStream();
                    accessFile.seek(startIndex);
                    int len;
                    byte[] buf = new byte[4096];
                    int total = 0;
                    while ((len = is.read(buf)) != -1) {
                        accessFile.write(buf, 0, len);
                        total += len;
                        RandomAccessFile progAccessFile = new RandomAccessFile(prog, "rwd");
                        progAccessFile.seek(seeks[threadId]);
                        progAccessFile.write((total + "").getBytes("utf-8"));
                        progAccessFile.close();
                    }
                    System.out.println(threadId + "号:线程下载完毕,total=" + total);
                    is.close();
                    accessFile.close();
                    synchronized (this) {
                        successThread++;
                        if (successThread == THREAD_COUNT)
                            prog.delete();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
